package com.occludens.admin.datamodel;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.googlecode.objectify.Ref;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Load;
import com.googlecode.objectify.annotation.Parent;
import com.googlecode.objectify.annotation.Subclass;

@Subclass(index=true)
@Cache
public class Interface extends AdminObjectDataModel {
	@Parent private Ref<Interface> derived;
	@Load private List<Ref<Attribute>> attributes = new ArrayList<Ref<Attribute>>();
	@Load private List<Ref<Type>> allowedTypes = new ArrayList<Ref<Type>>();
	@Load private List<Ref<Relationship>> allowedRelationships = new ArrayList<Ref<Relationship>>();

	protected Interface() {} // Mandatory for Objectify

	public Interface(String name) {
		super(name);
	}

	public Interface(String name, String description, Interface derivedFrom, List<Attribute> attributes, List<Type> allowedTypes, List<Relationship> allowedRelationships) {
		super(name);
		this.setDescription(description);
		this.setDerived(derivedFrom);
		this.setAttributes(attributes);
		this.setAllowedTypes(allowedTypes);
		this.setAllowedRelationships(allowedRelationships);
	}

	public Interface getDerived() {
		return this.derived.get();
	}
	
	public void setDerived (Interface derivedFrom) {
		this.derived = Ref.create(derivedFrom);
	}

	public List<Attribute> getAttributes() {
		List<Attribute> returnList = new ArrayList<Attribute>();
		Iterator<Ref<Attribute>> attributesItr = this.attributes.iterator();
		while (attributesItr.hasNext()) {
			returnList.add(attributesItr.next().get());
		}//End of while attributesItr
		return returnList;
	}

	public void setAttributes(List<Attribute> attributes) {
		Iterator<Attribute> attributesItr = attributes.iterator();
		while (attributesItr.hasNext()) {
			Ref<Attribute> attributeRef = Ref.create(attributesItr.next());
			if (!this.attributes.contains(attributeRef)) {
				this.attributes.add(attributeRef);
			}
		}//End of while attributesItr
	}

	public void addAttributes(Attribute... attributes) {
		for (int i=0; i<attributes.length; i++) {
			Ref<Attribute> attributeRef = Ref.create(attributes[i]);
			if (!this.attributes.contains(attributeRef)) {
				this.attributes.add(attributeRef);
			}
		}
	}

	public void removeAttributes(Attribute... attributes) {
		for (int i=0; i<attributes.length; i++) {
			Ref<Attribute> attributeRef = Ref.create(attributes[i]);
			if (this.attributes.contains(attributeRef)) {
				this.attributes.remove(attributeRef);
			}
		}
	}

	public List<Type> getAllowedTypes() {
		List<Type> returnList = new ArrayList<Type>();
		Iterator<Ref<Type>> typesItr = this.allowedTypes.iterator();
		while (typesItr.hasNext()) {
			returnList.add(typesItr.next().get());
		}//End of while typesItr
		return returnList;
	}

	public void setAllowedTypes(List<Type> types) {
		Iterator<Type> typesItr = types.iterator();
		while (typesItr.hasNext()) {
			Ref<Type> typeRef = Ref.create(typesItr.next());
			if (!this.allowedTypes.contains(typeRef)) {
				this.allowedTypes.add(typeRef);
			}
		}//End of while typesItr
	}

	public void addAllowedTypes(Type... types) {
		for (int i=0; i<types.length; i++) {
			Ref<Type> typeRef = Ref.create(types[i]);
			if (!this.allowedTypes.contains(typeRef)) {
				this.allowedTypes.add(typeRef);
			}
		}

	}

	public void removeAllowedTypes(Type... types) {
		for (int i=0; i<types.length; i++) {
			Ref<Type> typeRef = Ref.create(types[i]);
			if (this.allowedTypes.contains(typeRef)) {
				this.allowedTypes.remove(typeRef);
			}
		}
	}

	public List<Relationship> getAllowedRelationships() {
		List<Relationship> returnList = new ArrayList<Relationship>();
		Iterator<Ref<Relationship>> relationshipsItr = this.allowedRelationships.iterator();
		while (relationshipsItr.hasNext()) {
			returnList.add(relationshipsItr.next().get());
		}//End of while typesItr
		return returnList;
	}

	public void setAllowedRelationships(List<Relationship> relationships) {
		Iterator<Relationship> relationshipsItr = relationships.iterator();
		while (relationshipsItr.hasNext()) {
			Ref<Relationship> relationshipRef = Ref.create(relationshipsItr.next());
			if (!this.allowedRelationships.contains(relationshipRef)) {
				this.allowedRelationships.add(relationshipRef);
			}
		}//End of while typesItr
	}

	public void addAllowedRelationships(Relationship... relationships) {
		for (int i=0; i<relationships.length; i++) {
			Ref<Relationship> relationshipRef = Ref.create(relationships[i]);
			if (!this.allowedRelationships.contains(relationshipRef)) {
				this.allowedRelationships.add(relationshipRef);
			}
		}
	}

	public void removeAllowedRelationships(Relationship... relationships) {
		for (int i=0; i<relationships.length; i++) {
			Ref<Relationship> relationshipRef = Ref.create(relationships[i]);
			if (this.allowedRelationships.contains(relationshipRef)) {
				this.allowedRelationships.remove(relationshipRef);
			}
		}
	}

}
